#pragma once

#include <boost/random.hpp>
#include <boost/unordered_set.hpp>
#include <math/quadtree.hpp>




struct test_quadtree
{
private:

   typedef float                                         float_type;
   typedef math::vector2<float_type>                     vector2;
   typedef math::size2<float_type>                       size2;
   typedef math::rectangle<float_type>                   rectangle;
   typedef std::size_t                                   element;
   typedef math::quadtree_adaptor<element, float_type>   value_type;
   typedef math::quadtree<value_type, float_type>        quadtree;
   typedef quadtree::value_type                          value_type;
   typedef quadtree::rect_filter                         rect_filter;
   typedef boost::unordered_set<value_type>              set;

   typedef quadtree::bucket_iterator             bucket_iterator;
   typedef quadtree::const_bucket_iterator       const_bucket_iterator;
   typedef quadtree::basic_bucket_iterator<quadtree, rect_filter>   bucket_filter_iterator;
   typedef quadtree::basic_bucket_iterator<const quadtree, rect_filter>   const_bucket_filter_iterator;
   typedef quadtree::iterator                    iterator;
   typedef quadtree::const_iterator              const_iterator;
   typedef quadtree::flat_iterator               flat_iterator;


   // Stuff for random number generation (especially coordinates)
   typedef boost::mt19937                                 rng;
   typedef boost::uniform_real<float_type>                distribution;
   typedef boost::variate_generator<rng&, distribution>   die;

private:

   uint32   m_seed;

public:

   test_quadtree();
   void operator()();

private:

   void test_construction();
   void test_insertion();
   void test_filter();

   /**
    * Inserts the given number of randomly generated elements into
    * the quadtree.
    *
    * @param tree          the tree to populate
    * @param numElements   the number of elements to generate & insert
    */
   void fill(quadtree& tree, std::size_t numElements);

   /**
    * Inserts the same values into the set as fill() would insert
    * into the quadtree, when using the same number. This function doesn't
    * iterate over the values of the quadtree, but uses the tree's rectangle
    * and number of elements to generate the same values.
    *
    * @param tree    the set to fill with data
    * @param qtree   the quadtree to fetch the data from
    */
   void fill(set& tree, const quadtree& qtree);
};
///////////////////////////////////////////////////////////////////////////////////////////////////
